<?php
declare(strict_types=1);

namespace app\controller;
use app\BaseController;
use think\facade\Db;
use think\facade\Validate;

class CangkuTransaction extends BaseController
{
    /**
     * 成功返回
     */
    protected function success($msg = '', $data = null)
    {
        return json([
            'code' => 1,
            'message' => $msg,
            'data' => $data
        ]);
    }

    /**
     * 失败返回
     */
    protected function error($msg = '', $data = null)
    {
        return json([
            'code' => 0,
            'message' => $msg,
            'data' => $data
        ]);
    }

    /**
     * 获取库存交易记录列表
     */
    public function getList()
    {
        $page = input('pageNo', 1, 'intval');
        $limit = input('pageSize', 10, 'intval');
        $orderNo = input('orderNo', '');
        $transactionType = input('transactionType', '');

        $where = [];
        if (!empty($orderNo)) {
            $where[] = ['t.order_no', 'like', "%{$orderNo}%"];
        }
        if (!empty($transactionType)) {
            $where[] = ['t.transaction_type', '=', $transactionType];
        }

        $count = Db::name('inventory_transaction')
            ->alias('t')
            ->where($where)
            ->count();

        $list = Db::name('inventory_transaction')
            ->alias('t')
            ->join('material_category m', 't.material_id = m.id')
            ->join('shelf s', 't.shelf_id = s.id')
            ->field('t.*, m.material_name, s.shelf_code')
            ->where($where)
            ->order('t.id', 'desc')
            ->page($page, $limit)
            ->select()
            ->toArray();

        return $this->success('获取成功', [
            'list' => $list,
            'total' => $count
        ]);
    }

    /**
     * 添加库存交易记录
     */
    public function addTransaction()
    {
        $data = input('post.');
        
        // 添加调试日志
        trace('接收到的交易记录数据: ' . json_encode($data), 'info');
        
        // 处理序列号批量入库
        if (isset($data['serials']) && is_array($data['serials'])) {
            return $this->addBatchTransaction($data);
        }

        // 验证数据
        $validate = Validate::rule([
            'transaction_type' => 'require',
            'order_no' => 'require|unique:inventory_transaction',
            'admin_id' => 'require|number',
            'admin_name' => 'require',
            'material_id' => 'require|number',
            'shelf_id' => 'require|number',
            'quantity' => 'require|number|gt:0',
        ]);

        if (!$validate->check($data)) {
            trace('数据验证失败: ' . $validate->getError(), 'error');
            return $this->error($validate->getError());
        }

        // 检查物料是否存在
        $material = Db::name('material_category')->where('id', $data['material_id'])->find();
        trace('查询物料: ' . json_encode($material), 'info');
        if (!$material) {
            return $this->error('物料不存在');
        }

        // 检查库位是否存在
        $shelf = Db::name('shelf')->where('id', $data['shelf_id'])->find();
        trace('查询库位: ' . json_encode($shelf), 'info');
        if (!$shelf) {
            return $this->error('库位不存在');
        }

        // 开启事务
        Db::startTrans();
        try {
            // 添加交易记录
            trace('准备插入数据到inventory_transaction表', 'info');
            $id = Db::name('inventory_transaction')->insertGetId([
                'transaction_type' => $data['transaction_type'],
                'order_no' => $data['order_no'],
                'related_order_no' => $data['related_order_no'] ?? null,
                'applicant_id' => $data['applicant_id'] ?? null,
                'applicant_name' => $data['applicant_name'] ?? null,
                'inspector_name' => $data['inspector_name'] ?? null,
                'admin_id' => $data['admin_id'],
                'admin_name' => $data['admin_name'],
                'material_id' => $data['material_id'],
                'shelf_id' => $data['shelf_id'],
                'material_type' => $data['material_type'] ?? '标准件',
                'quantity' => $data['quantity'],
                'batch_no' => $data['batch_no'] ?? null,
                'serial_no' => $data['serial_no'] ?? null,
                'inspection_image' => $data['inspection_image'] ?? null,
                'outbound_image' => $data['outbound_image'] ?? null,
                'remark' => $data['remark'] ?? null,
                'transaction_time' => date('Y-m-d H:i:s')
            ]);
            trace('数据插入成功，ID: ' . $id, 'info');

            // 更新物料库存
            if ($data['transaction_type'] === '入库') {
                trace('执行入库操作，更新物料库存', 'info');
                Db::name('material_category')
                    ->where('id', $data['material_id'])
                    ->inc('current_quantity', $data['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
                trace('入库库存更新成功', 'info');
            } elseif ($data['transaction_type'] === '出库') {
                // 检查库存是否足够
                if ($material['current_quantity'] < $data['quantity']) {
                    throw new \Exception('库存不足，无法出库');
                }
                
                trace('执行出库操作，更新物料库存', 'info');
                Db::name('material_category')
                    ->where('id', $data['material_id'])
                    ->dec('current_quantity', $data['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
                trace('出库库存更新成功', 'info');
            } elseif ($data['transaction_type'] === '退回') {
                trace('执行退回操作，更新物料库存', 'info');
                Db::name('material_category')
                    ->where('id', $data['material_id'])
                    ->inc('current_quantity', $data['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
                trace('退回库存更新成功', 'info');
            }

            Db::commit();
            trace('事务提交成功', 'info');
            return $this->success('添加成功', ['id' => $id]);
        } catch (\Exception $e) {
            Db::rollback();
            trace('发生异常: ' . $e->getMessage(), 'error');
            return $this->error('添加失败：' . $e->getMessage());
        }
    }

    /**
     * 处理批量序列号入库
     */
    private function addBatchTransaction($data)
    {
        if (empty($data['serials']) || !is_array($data['serials'])) {
            return $this->error('序列号数据格式错误');
        }

        // 检查物料是否存在
        $material = Db::name('material_category')->where('id', $data['material_id'])->find();
        if (!$material) {
            return $this->error('物料不存在');
        }

        // 检查库位是否存在
        $shelf = Db::name('shelf')->where('id', $data['shelf_id'])->find();
        if (!$shelf) {
            return $this->error('库位不存在');
        }

        // 开启事务
        Db::startTrans();
        try {
            $total_quantity = 0;
            
            // 批量添加序列号记录
            foreach ($data['serials'] as $serial) {
                Db::name('inventory_transaction')->insert([
                    'transaction_type' => $data['transaction_type'],
                    'order_no' => $data['order_no'],
                    'related_order_no' => $data['related_order_no'] ?? null,
                    'applicant_id' => $data['applicant_id'] ?? null,
                    'applicant_name' => $data['applicant_name'] ?? null,
                    'inspector_name' => $data['inspector_name'] ?? null,
                    'admin_id' => $data['admin_id'],
                    'admin_name' => $data['admin_name'],
                    'material_id' => $data['material_id'],
                    'shelf_id' => $data['shelf_id'],
                    'material_type' => $data['material_type'] ?? '标准件',
                    'quantity' => $serial['quantity'],
                    'batch_no' => $data['batch_no'] ?? null,
                    'serial_no' => $serial['serial_no'],
                    'inspection_image' => $data['inspection_image'] ?? null,
                    'outbound_image' => $data['outbound_image'] ?? null,
                    'remark' => $data['remark'] ?? null,
                    'transaction_time' => date('Y-m-d H:i:s')
                ]);
                
                $total_quantity += $serial['quantity'];
            }
            
            // 更新物料库存
            Db::name('material_category')
                ->where('id', $data['material_id'])
                ->inc('current_quantity', $total_quantity)
                ->update([
                    'last_update_time' => date('Y-m-d H:i:s')
                ]);

            Db::commit();
            return $this->success('批量添加成功', ['quantity' => $total_quantity]);
        } catch (\Exception $e) {
            Db::rollback();
            return $this->error('批量添加失败：' . $e->getMessage());
        }
    }

    /**
     * 编辑库存交易记录
     */
    public function editTransaction()
    {
        $data = input('post.');

        // 验证数据
        $validate = Validate::rule([
            'id' => 'require|number',
            'transaction_type' => 'require',
            'admin_id' => 'require|number',
            'admin_name' => 'require',
            'material_id' => 'require|number',
            'shelf_id' => 'require|number',
            'quantity' => 'require|number|gt:0',
        ]);

        if (!$validate->check($data)) {
            return $this->error($validate->getError());
        }

        // 检查交易记录是否存在
        $transaction = Db::name('inventory_transaction')->where('id', $data['id'])->find();
        if (!$transaction) {
            return $this->error('交易记录不存在');
        }

        // 检查物料是否存在
        $material = Db::name('material_category')->where('id', $data['material_id'])->find();
        if (!$material) {
            return $this->error('物料不存在');
        }

        // 检查库位是否存在
        $shelf = Db::name('shelf')->where('id', $data['shelf_id'])->find();
        if (!$shelf) {
            return $this->error('库位不存在');
        }

        // 开启事务
        Db::startTrans();
        try {
            // 先恢复原交易对库存的影响
            if ($transaction['transaction_type'] === '入库') {
                Db::name('material_category')
                    ->where('id', $transaction['material_id'])
                    ->dec('current_quantity', $transaction['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
            } elseif ($transaction['transaction_type'] === '出库') {
                Db::name('material_category')
                    ->where('id', $transaction['material_id'])
                    ->inc('current_quantity', $transaction['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
            } elseif ($transaction['transaction_type'] === '退回') {
                Db::name('material_category')
                    ->where('id', $transaction['material_id'])
                    ->dec('current_quantity', $transaction['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
            }

            // 更新交易记录
            Db::name('inventory_transaction')
                ->where('id', $data['id'])
                ->update([
                    'transaction_type' => $data['transaction_type'],
                    'related_order_no' => $data['related_order_no'] ?? null,
                    'applicant_id' => $data['applicant_id'] ?? null,
                    'applicant_name' => $data['applicant_name'] ?? null,
                    'inspector_name' => $data['inspector_name'] ?? null,
                    'admin_id' => $data['admin_id'],
                    'admin_name' => $data['admin_name'],
                    'material_id' => $data['material_id'],
                    'shelf_id' => $data['shelf_id'],
                    'material_type' => $data['material_type'] ?? '标准件',
                    'quantity' => $data['quantity'],
                    'batch_no' => $data['batch_no'] ?? null,
                    'serial_no' => $data['serial_no'] ?? null,
                    'inspection_image' => $data['inspection_image'] ?? $transaction['inspection_image'],
                    'outbound_image' => $data['outbound_image'] ?? $transaction['outbound_image'],
                    'remark' => $data['remark'] ?? null,
                ]);

            // 应用新交易对库存的影响
            if ($data['transaction_type'] === '入库') {
                Db::name('material_category')
                    ->where('id', $data['material_id'])
                    ->inc('current_quantity', $data['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
            } elseif ($data['transaction_type'] === '出库') {
                // 检查库存是否足够
                $currentMaterial = Db::name('material_category')->where('id', $data['material_id'])->find();
                if ($currentMaterial['current_quantity'] < $data['quantity']) {
                    throw new \Exception('库存不足，无法出库');
                }
                
                Db::name('material_category')
                    ->where('id', $data['material_id'])
                    ->dec('current_quantity', $data['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
            } elseif ($data['transaction_type'] === '退回') {
                Db::name('material_category')
                    ->where('id', $data['material_id'])
                    ->inc('current_quantity', $data['quantity'])
                    ->update([
                        'last_update_time' => date('Y-m-d H:i:s')
                    ]);
            }

            Db::commit();
            return $this->success('编辑成功');
        } catch (\Exception $e) {
            Db::rollback();
            return $this->error('编辑失败：' . $e->getMessage());
        }
    }

    /**
     * 删除库存交易记录
     */
    public function deleteTransaction()
    {
        $id = input('id', 0, 'intval');
        $ids = input('ids', '');

        if (empty($id) && empty($ids)) {
            return $this->error('参数错误');
        }

        // 开启事务
        Db::startTrans();
        try {
            if (!empty($id)) {
                // 单个删除
                $transaction = Db::name('inventory_transaction')->where('id', $id)->find();
                if (!$transaction) {
                    return $this->error('交易记录不存在');
                }

                // 恢复库存
                if ($transaction['transaction_type'] === '入库') {
                    Db::name('material_category')
                        ->where('id', $transaction['material_id'])
                        ->dec('current_quantity', $transaction['quantity'])
                        ->update([
                            'last_update_time' => date('Y-m-d H:i:s')
                        ]);
                } elseif ($transaction['transaction_type'] === '出库') {
                    Db::name('material_category')
                        ->where('id', $transaction['material_id'])
                        ->inc('current_quantity', $transaction['quantity'])
                        ->update([
                            'last_update_time' => date('Y-m-d H:i:s')
                        ]);
                } elseif ($transaction['transaction_type'] === '退回') {
                    Db::name('material_category')
                        ->where('id', $transaction['material_id'])
                        ->dec('current_quantity', $transaction['quantity'])
                        ->update([
                            'last_update_time' => date('Y-m-d H:i:s')
                        ]);
                }

                Db::name('inventory_transaction')->where('id', $id)->delete();
            } else {
                // 批量删除
                $idArr = explode(',', $ids);
                foreach ($idArr as $id) {
                    $transaction = Db::name('inventory_transaction')->where('id', $id)->find();
                    if ($transaction) {
                        // 恢复库存
                        if ($transaction['transaction_type'] === '入库') {
                            Db::name('material_category')
                                ->where('id', $transaction['material_id'])
                                ->dec('current_quantity', $transaction['quantity'])
                                ->update([
                                    'last_update_time' => date('Y-m-d H:i:s')
                                ]);
                        } elseif ($transaction['transaction_type'] === '出库') {
                            Db::name('material_category')
                                ->where('id', $transaction['material_id'])
                                ->inc('current_quantity', $transaction['quantity'])
                                ->update([
                                    'last_update_time' => date('Y-m-d H:i:s')
                                ]);
                        } elseif ($transaction['transaction_type'] === '退回') {
                            Db::name('material_category')
                                ->where('id', $transaction['material_id'])
                                ->dec('current_quantity', $transaction['quantity'])
                                ->update([
                                    'last_update_time' => date('Y-m-d H:i:s')
                                ]);
                        }
                    }
                }
                Db::name('inventory_transaction')->whereIn('id', $idArr)->delete();
            }

            Db::commit();
            return $this->success('删除成功');
        } catch (\Exception $e) {
            Db::rollback();
            return $this->error('删除失败：' . $e->getMessage());
        }
    }

    /**
     * 生成订单号
     */
    public function generateOrderNo()
    {
        $type = input('type', 'RK'); // 默认为入库单号
        $prefix = in_array($type, ['RK', 'CK', 'TH']) ? $type : 'RK';
        $date = date('Ym');
        $random = mt_rand(1000, 9999);
        $orderNo = $prefix . $date . $random;

        // 检查订单号是否已存在
        $exists = Db::name('inventory_transaction')->where('order_no', $orderNo)->find();
        if ($exists) {
            return $this->generateOrderNo(); // 递归重新生成
        }

        return $this->success('生成成功', $orderNo);
    }

    /**
     * 生成批次号
     */
    public function generateBatchNo()
    {
        $day = mt_rand(10, 31); // 生成两位日期数字
        $randomChars = $this->generateRandomString(2); // 生成两位随机字母
        $date = date('ym'); // 年月
        $batchNo = "P-{$day}{$randomChars}-{$date}";

        return $this->success('生成成功', $batchNo);
    }

    /**
     * 生成序列号
     */
    public function generateSerialNo()
    {
        $prefix = 'XHL';
        $date = date('ym');
        $count = Db::name('inventory_transaction')
            ->where('serial_no', 'like', "{$prefix}{$date}-%")
            ->count();
        $serial = str_pad((string)($count + 1), 6, '0', STR_PAD_LEFT);
        $serialNo = "{$prefix}{$date}-{$serial}";

        return $this->success('生成成功', $serialNo);
    }

    /**
     * 生成指定长度的随机字符串（字母）
     */
    private function generateRandomString($length = 2)
    {
        $characters = 'ABCDEFGHJKLMNPQRSTUVWXYZ'; // 去掉容易混淆的字符
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }
} 